﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.Features2D;
using System.Drawing;
using iMapa.Backend.ActionPlugin;
using System.IO;
using iMapa.Utils;
using iMapa.Helper;
using iMapa.UI.ModelView.Main;

namespace iMapa.Backend
{
    public class InteractMapLoader
    {
        private static readonly string mapfilename = "map.xml";

        public static string temppath = Path.GetTempPath()+"iMapa" + DateTime.Now.Ticks+"\\";

        public static string applicationDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        public static string applicationDir = AppDomain.CurrentDomain.BaseDirectory;

        public static bool saveOnExit;

        public static List<InteractMapGroup> LoadInteractMaps()
        {
            PluginHandler.getInstance();

            CrashRecovery();

            List<InteractMapGroup> mapgroups = new List<InteractMapGroup>();
            UnpackAndCreateTemp();

            System.IO.DirectoryInfo maps = new System.IO.DirectoryInfo(temppath);
            foreach (System.IO.DirectoryInfo mapdir in maps.GetDirectories())
            {
                InteractMap map = Load(mapdir.Name);
                string groupname = map.ParentGroup;
                InteractMapGroup targetGroup = null;
                foreach (InteractMapGroup img in mapgroups)
                {
                    if (groupname != null && groupname.Equals(img.Name))
                    {
                        targetGroup = img;
                        break;
                    }
                }
                if (targetGroup == null)
                {
                    targetGroup = new InteractMapGroup();
                    targetGroup.Name = groupname;
                    mapgroups.Add(targetGroup);
                }
                targetGroup.Maps.Add(map);
            }
            return mapgroups;
        }

        private static void CrashRecovery()
        {
            System.IO.DirectoryInfo maps = new System.IO.DirectoryInfo(Path.GetTempPath());
            foreach (System.IO.DirectoryInfo dir in maps.GetDirectories("iMapa*"))
            {
                Directory.Delete(dir.FullName, true);
            }
        }

        public static void Save(InteractMap interactMap)
        {
            Type[] extraTypes = new Type[1];
            extraTypes[0] = typeof(Image<Bgr, byte>);
            ObjectXMLSerializer<InteractMap>.Save(interactMap, GetInteractMapPath(interactMap.Name) +mapfilename, extraTypes);
            foreach (InteractObject io in interactMap.InteractObjects)
            {
                if (io.ActionType != null)
                {
                    io.ActionParams.PersistToFile(GetInteractMapPath(interactMap.Name) + io.ActionParams.GetID());
                }
            }
        }

        public static InteractMap Load(string interactMapName)
        {
            Type[] extraTypes = new Type[1];
            extraTypes[0] = typeof(Image<Bgr, byte>);
            InteractMap im= ObjectXMLSerializer<InteractMap>.Load(GetInteractMapPath(interactMapName) + mapfilename, extraTypes);
            im.InitializeInteractMap();
            im.LoadActions();
            return im;
        }



        public static string GetInteractMapPath(string interactMap)
        {
            string defaultpath = temppath + interactMap + "\\";
            if (!Directory.Exists(defaultpath))
            {
                Directory.CreateDirectory(defaultpath);
            }
            return defaultpath;
        }

        public static void UnpackAndCreateTemp()
        {
            string sPath = applicationDataDir + "\\iMaps\\";
            if (!Directory.Exists(sPath))
            {
                 //??
                return;
            }

            if (Directory.Exists(temppath))
            {
                Directory.Delete(temppath,true);
            }
            Directory.CreateDirectory(temppath);

            System.IO.FileInfo mapsZips = new System.IO.FileInfo(sPath);
            foreach (System.IO.FileInfo mapzip in mapsZips.Directory.GetFiles("*.imapa"))
            {
                string tempMapPath= temppath + mapzip.Name.Replace(".imapa","");
                if(!Directory.Exists(tempMapPath)){
                    Directory.CreateDirectory(tempMapPath);
                }
                Zipper.Extract(mapzip.FullName, tempMapPath);
            }
            
        }

        public static void PackAndRemoveTemp(object o)
        {
            ProgressIndicatorViewModel model = (ProgressIndicatorViewModel)o;
            string sPath = applicationDataDir + "\\iMaps\\";
            if (Directory.Exists(sPath))
            {
                Directory.Delete(sPath,true);
            } 
            Directory.CreateDirectory(sPath);

            System.IO.FileInfo mapsDir = new System.IO.FileInfo(temppath);
            model.Steps = mapsDir.Directory.GetDirectories().Length;
            foreach (System.IO.DirectoryInfo map in mapsDir.Directory.GetDirectories())
            {
                string[] files = GetListOfFiles(map.Name);
                Zipper.Zip(sPath+map.Name + ".imapa", files);
                model.CurrentStep = model.CurrentStep + 1;
            }
            Directory.Delete(temppath,true);
            model.CurrentStep = model.CurrentStep + 1;
        }

        private static string[] GetListOfFiles(string map)
        {
            string pathBase = temppath + map + "\\";
            List<string> result = new List<string>();
            result.Add(pathBase+mapfilename);
            InteractMap imapa = Load(map);
            foreach (InteractObject io in imapa.InteractObjects)
            {
                if (io.ActionParamsFile != null)
                {
                    result.Add(pathBase+ io.ActionParamsFile);
                    //include all resource files
                    string[] resources = io.ActionParams.GetResourceFiles();
                    if (resources != null && resources.Length > 0)
                    {
                        foreach (string res in resources)
                        {
                            if (File.Exists(res))
                            {
                                result.Add(res);
                            }
                            
                        }
                    }
                }
            }
            return result.ToArray() ;
        }
    }
}
